#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <vector>
#include <poll.h>
#include <sys/time.h>
#include "Socket.hpp"
#include "Log.hpp"
#include "ThreadPool.hpp"
#define REVENTSZERO (short)0
#define FD_ARRAY_DEFAULTNUMS 1024
static const int gdefault = -1;
using task_t = std::function<void()>;
ThreadPool<task_t> Pool;

using namespace sock_ns;
using namespace ns_log;
class PollServer
{
public:
    PollServer(uint16_t port) : _port(port), _listensocket(std::make_unique<Tcp_socket>())
    {
        _listensocket->BuildListenSocket(_port);
        // 启动线程池
        Pool.Init();
        Pool.start();
        fd_array.resize(FD_ARRAY_DEFAULTNUMS);
    }
    ~PollServer()
    {
        Pool.Stop();
    }
    void InitServer() // 初始化fd_array
    {
        for (int i = 0; i < fd_array.size(); i++)
        {
            fd_array[i].fd = gdefault;
            fd_array[i].events = POLLIN;
            fd_array[i].revents = REVENTSZERO;
        }
        fd_array[0].fd = _listensocket->SockFd();
    }
    void Accepter()
    {
        // 监听套接字处理
        // 有读事件就绪！
        InetAddr addr;
        int sockfd = _listensocket->AcceptSocket(&addr);
        if (sockfd > 0)
        {
            bool flag = false; // 标记位，用于判断fd_array是否已满
            LOG(INFO, "Get a new link,mssage = %s\n", addr.GetAddrStr().c_str());
            // 将新的文件fd交给poll统一监管！
            for (int i = 1; i < fd_array.size(); i++)
            {
                if (fd_array[i].fd == gdefault)
                {
                    flag = true;
                    fd_array[i].fd = sockfd;
                    fd_array[i].events = POLLIN ;
                    fd_array[i].revents = REVENTSZERO;
                    break;
                }
            }
            if (!flag)
            {
                LOG(WARNING, "Server is full,Capacity is expanding!\n");
                // 扩容
                fd_array.reserve(fd_array.size() * 2);
                struct pollfd newpollfd = {sockfd, POLLIN, REVENTSZERO};
                fd_array.push_back(newpollfd);
            }
        }
    }
    void HandleIo(int pos)
    {
        // 普通套接字处理
        char buffer[1024];
        ssize_t n = ::recv(fd_array[pos].fd, &buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << "Client say# " << buffer << std::endl;
            std::string send_str = "[server info]@ ";
            send_str += buffer;
            ::send(fd_array[pos].fd, send_str.c_str(), send_str.size(), 0);
        }
        else if (n == 0)
        {
            ::close(fd_array[pos].fd);
            fd_array[pos].fd = gdefault;
            LOG(INFO, "client quit...\n");
        }
        else
        {
            ::close(fd_array[pos].fd);
            fd_array[pos].fd = gdefault;
            LOG(ERROR, "recv error!\n");
        }
    }
    void HandleHappen()
    {
        for (int i = 0; i < fd_array.size(); i++)
        {
            if (fd_array[i].fd == gdefault)
                continue;
            // 是否在fd_array中?
            if (fd_array[i].revents & POLLIN)
            {
                if (_listensocket->SockFd() == fd_array[i].fd)
                {
                    task_t task = std::bind(&PollServer::Accepter, this);
                    // 处理新的连接;
                    Pool.Push(task);
                }
                else
                {
                    task_t task = std::bind(&PollServer::HandleIo, this, i);
                    // 处理正常IO;
                    Pool.Push(task);
                }
            }
        }
    }
    void PrintDebug()
    {
        std::cout << "list: ";
        for (int i = 0; i < fd_array.size(); i++)
        {
            if (fd_array[i].fd == gdefault)
                continue;
            std::cout << fd_array[i].fd << " ";
        }
        std::cout << std::endl;
    }
    void Loop()
    {
        int timeout = -1; // 超时时间--毫秒为单位
        while (true)
        {
            int n = ::poll(&fd_array[0], fd_array.size(), timeout);
            switch (n)
            {
            case 0:
                LOG(INFO, "timeout...\n");
                break;
            case -1:
                LOG(ERROR, "poll error!\n");
                break;
            default:
                LOG(INFO, "有事件就绪,待处理！\n");
                HandleHappen();
                PrintDebug();
                break;
            }
        }
    }

private:
    uint16_t _port;                        // 端口号
    std::unique_ptr<Socket> _listensocket; // 监听套接字
    std::vector<struct pollfd> fd_array;   // 辅助数组,记录所有合法的文件fd
};